﻿#region Copyright

// The contents of this file are subject to the Mozilla Public License
//  Version 1.1 (the "License"); you may not use this file except in compliance
//  with the License. You may obtain a copy of the License at
//  
//  http://www.mozilla.org/MPL/
//  
//  Software distributed under the License is distributed on an "AS IS"
//  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
//  License for the specific language governing rights and limitations under 
//  the License.
//  
//  The Initial Developer of the Original Code is Robert Smyth.
//  Portions created by Robert Smyth are Copyright (C) 2008.
//  
//  All Rights Reserved.

#endregion

using System;
using NUnitGrid.Framework;
using NUnitGrid.Framework.Logging;
using NUnitGrid.Framework.Pipes;
using NUnitGrid.Protocol;
using NUnitGrid.Protocol.Commands;
using NUnitGrid.Server.Plugins.Nodes.Node.States;


namespace NUnitGrid.Server.Plugins.Nodes.Node
{
    public class GridNodeProxy : IGridNode, IReadInfoListener, IPipeListener
    {
        private readonly IGridNodeMetrics gridNodeMetrics;
        private readonly IGridNodeListener<IGridNodeMetrics> listener;
        private readonly ILogger logger;
        private readonly IGridProtocol protocol;
        private readonly IStateEngine<IGridNodeState> stateEngine;

        public GridNodeProxy(IStateEngine<IGridNodeState> stateEngine, IServerStateFactory serverStateFactory,
                             ILogger logger, IGridNodeListener<IGridNodeMetrics> listener, IGridProtocol protocol,
                             IGridNodeMetrics gridNodeMetrics)
        {
            this.stateEngine = stateEngine;
            this.logger = logger;
            this.listener = listener;
            this.protocol = protocol;
            this.gridNodeMetrics = gridNodeMetrics;
            stateEngine.ChangeState(serverStateFactory.CreateLinkNotConnectedState());
        }

        public string MachineName
        {
            get { return gridNodeMetrics.MachineName; }
        }

        public int NumberOfProcessors
        {
            get { return gridNodeMetrics.NumberOfProcessors; }
        }

        public int ProcessorMHz
        {
            get { return gridNodeMetrics.ProcessorMHz; }
        }

        public bool Busy
        {
            get { return gridNodeMetrics.Busy; }
        }

        public int TasksCount
        {
            get { return gridNodeMetrics.TasksCount; }
        }

        public TimeSpan CurrentTaskRunTime
        {
            get { return gridNodeMetrics.CurrentTaskRunTime; }
        }

        public int FailedTasksCount
        {
            get { return gridNodeMetrics.FailedTasksCount; }
        }

        public string Nickname
        {
            get { return gridNodeMetrics.Nickname; }
        }

        public string SoftwareVersion
        {
            get { return gridNodeMetrics.SoftwareVersion; }
        }

        public void Start()
        {
            protocol.Start();
            stateEngine.CurrentState.Start();
        }

        public void RunTask(IRunOnGridTask task, IRunOnGridTaskListener taskProgressListener)
        {
            stateEngine.CurrentState.RunTask(task, taskProgressListener, listener);
            gridNodeMetrics.TasksCount++;
        }

        public void Stop()
        {
            protocol.Stop();
        }

        void IPipeListener.OnConnectedChanged(bool connected)
        {
            logger.Verbose.Write("Node's link connected - {0}", connected);
            stateEngine.CurrentState.OnConnectedChanged(connected);
        }

        void IReadInfoListener.OnInfoRead(bool succeeded, string machineName, string nickName, int numberOfProcessors,
                                          int processorMHz, string softwareVersion)
        {
            if (succeeded)
            {
                logger.Verbose.Write("Node information read");
                if (gridNodeMetrics.Update(machineName, nickName, numberOfProcessors, processorMHz, softwareVersion))
                {
                    listener.OnChange(gridNodeMetrics);
                }
            }
        }
    }
}